package pac

import (
	"fmt"
	"slgw_web/serial/util"
	"strconv"

	models "openzbox.com/frame/echo/models/sl_gw01"
	"openzbox.com/protocol/modbus"
)

const (
	testslaveID1 = 1
	testslaveID2 = 2
)

type NodeRegiste struct {
	slaveID int
	coilsAddrStart, coilsQuantity,
	discreteAddrStart, discreteQuantity,
	inputAddrStart, inputQuantity,
	holdingAddrStart, holdingQuantity uint16
}

var NodeRegisteList []NodeRegiste

func ModbusTCPCServer(DeviceInfo models.DeviceInfo, deviceInfoDetail []models.DeviceInfo_Detail) []models.NodeRegisterList {
	NodeRegistes := NodeRegiste{}
	NodeRegistes.coilsAddrStart = 0
	NodeRegistes.discreteAddrStart = 0
	NodeRegistes.inputAddrStart = 0
	NodeRegistes.holdingAddrStart = 0
	for _, detail := range deviceInfoDetail {
		if DeviceInfo.ID == detail.Device_ID {
			n, err := strconv.Atoi(detail.ModbusTCPSlaveID)
			if err == nil {
				if len(NodeRegisteList) == 0 {
					//第一个直接插入
					NodeRegistes.slaveID = n
					if *detail.ModbusTCPType == 1 {
						//功能码1
						NodeRegistes.coilsQuantity = *detail.ModbusTCPAddressID
					} else if *detail.ModbusTCPType == 2 {
						//功能码2
						NodeRegistes.discreteQuantity = *detail.ModbusTCPAddressID
					} else if *detail.ModbusTCPType == 3 {
						//功能码3
						NodeRegistes.holdingQuantity = *detail.ModbusTCPAddressID
					} else if *detail.ModbusTCPType == 4 {
						//功能码4
						NodeRegistes.inputQuantity = *detail.ModbusTCPAddressID
					}

					NodeRegisteList = append(NodeRegisteList, NodeRegistes)
				} else {
					for i, _ := range NodeRegisteList {

						//判断设备地址是否重复
						if NodeRegisteList[i].slaveID == n { //如果存在
							if *detail.ModbusTCPType == 1 {
								//功能码1
								if NodeRegisteList[i].coilsQuantity < *detail.ModbusTCPAddressID {
									NodeRegisteList[i].coilsQuantity = *detail.ModbusTCPAddressID
								}
							} else if *detail.ModbusTCPType == 2 {
								//功能码2
								if NodeRegisteList[i].discreteQuantity < *detail.ModbusTCPAddressID {
									NodeRegisteList[i].discreteQuantity = *detail.ModbusTCPAddressID
								}
							} else if *detail.ModbusTCPType == 3 {
								//功能码3
								if NodeRegisteList[i].holdingQuantity < *detail.ModbusTCPAddressID {
									NodeRegisteList[i].holdingQuantity = *detail.ModbusTCPAddressID
								}
							} else if *detail.ModbusTCPType == 4 {
								//功能码4
								if NodeRegisteList[i].inputQuantity < *detail.ModbusTCPAddressID {
									NodeRegisteList[i].inputQuantity = *detail.ModbusTCPAddressID
								}
							}
						} else { //不存在，新增一个
							//先判断是否已经存在其他的
							isBreak := false
							for i, _ := range NodeRegisteList {
								if NodeRegisteList[i].slaveID == n {
									//已存在
									isBreak = true
								}
							}
							if !isBreak {
								NodeRegistes.slaveID = n
								if *detail.ModbusTCPType == 1 {
									//功能码1
									NodeRegistes.coilsQuantity = *detail.ModbusTCPAddressID
								} else if *detail.ModbusTCPType == 2 {
									//功能码2
									NodeRegistes.discreteQuantity = *detail.ModbusTCPAddressID
								} else if *detail.ModbusTCPType == 3 {
									//功能码3
									NodeRegistes.holdingQuantity = *detail.ModbusTCPAddressID
								} else if *detail.ModbusTCPType == 4 {
									//功能码4
									NodeRegistes.inputQuantity = *detail.ModbusTCPAddressID
								}

								NodeRegisteList = append(NodeRegisteList, NodeRegistes)
							}
						}
					}
				}
			}
		}
	}
	fmt.Println("NodeRegisteList", NodeRegisteList)

	mbSrv := modbus.NewTCPServer()
	var NodeRegisterList []models.NodeRegisterList

	for _, nodeR := range NodeRegisteList {

		s1 := modbus.NewNodeRegister(byte(nodeR.slaveID),
			nodeR.coilsAddrStart, nodeR.coilsQuantity+3,
			nodeR.discreteAddrStart, nodeR.discreteQuantity+3,
			nodeR.inputAddrStart, nodeR.inputQuantity+3,
			nodeR.holdingAddrStart, nodeR.holdingQuantity+3)
		mbSrv.AddNodes(s1)
		// s1.WriteHoldings(0, []uint16{0x1121, 0x0122})
		NodeRegister := models.NodeRegisterList{
			SlaveID:      strconv.Itoa(nodeR.slaveID),
			NodeRegister: s1,
		}
		NodeRegisterList = append(NodeRegisterList, NodeRegister)
	}
	//DeviceInfo.ModbusTCPClient = NodeRegisterList //modbus连接状态
	fmt.Println("DeviceInfo.ModbusTCPClient", DeviceInfo.ModbusTCPClient)
	go func() {
		_ = mbSrv.ListenAndServe(*DeviceInfo.ModbusTCPIP + ":" + *DeviceInfo.ModbusTCPPORT)
	}()

	return NodeRegisterList
}

// 写入数据
func WriteModbusTCPData(sb models.DeviceInfo) {
	var collectDataList = util.CollectDataList        //采集到的信息
	var deviceDetailList = util.DeviceInfo_DetailList //对应的上报点位
	if len(collectDataList) > 0 && len(deviceDetailList) > 0 {
		for _, serialSlaveDetail := range collectDataList {
			for _, DeviceInfoDetailListData := range deviceDetailList {
				if sb.ID == DeviceInfoDetailListData.Device_ID {
					if serialSlaveDetail.ID == DeviceInfoDetailListData.Serial_Slave_Detail_ID { //如果采集到的是需要上报的点位
						value := serialSlaveDetail.Value
						for _, mc := range sb.ModbusTCPClient {
							if mc.SlaveID == DeviceInfoDetailListData.ModbusTCPSlaveID {
								if *DeviceInfoDetailListData.ModbusTCPType == 1 {
									if value != "0000" && value != "0001" {
										util.Error("modbus上行协议数据更新失败,name:" + sb.Name + ",ID:" + strconv.FormatInt(DeviceInfoDetailListData.ID, 10) + ",err:功能码1只能是bool类型,当前数据:" + value)
									} else {
										v := true
										if value == "0000" {
											v = false
										}
										err := mc.NodeRegister.WriteSingleCoil(*DeviceInfoDetailListData.ModbusTCPAddressID, v)
										if err != nil {
											util.Error("modbus上行协议数据更新失败,name:" + sb.Name + ",ID:" + strconv.FormatInt(DeviceInfoDetailListData.ID, 10) + ",err:功能码1数据写入失败," + err.Error())
										}
									}
								} else if *DeviceInfoDetailListData.ModbusTCPType == 2 {
									if value != "0000" && value != "0001" {
										util.Error("modbus上行协议数据更新失败,name:" + sb.Name + ",ID:" + strconv.FormatInt(DeviceInfoDetailListData.ID, 10) + ",err:功能码2只能是bool类型,当前数据:" + value)
									} else {
										v := true
										if value == "0000" {
											v = false
										}
										err := mc.NodeRegister.WriteSingleDiscrete(*DeviceInfoDetailListData.ModbusTCPAddressID, v)
										if err != nil {
											util.Error("modbus上行协议数据更新失败,name:" + sb.Name + ",ID:" + strconv.FormatInt(DeviceInfoDetailListData.ID, 10) + ",err:功能码2数据写入失败," + err.Error())
										}
									}
								} else if *DeviceInfoDetailListData.ModbusTCPType == 3 {
									//采集到的数据
									valueByte, err := stringToUint16Array(value) //转换后的数据
									if err != nil {
										util.Error("modbus上行协议数据更新失败,name:" + sb.Name + ",ID:" + strconv.FormatInt(DeviceInfoDetailListData.ID, 10) + ",err:功能码3 " + err.Error())
									}
									err = mc.NodeRegister.WriteHoldings(*DeviceInfoDetailListData.ModbusTCPAddressID, valueByte)
									if err != nil {
										util.Error("modbus上行协议数据更新失败,name:" + sb.Name + ",ID:" + strconv.FormatInt(DeviceInfoDetailListData.ID, 10) + ",err:功能码3数据写入失败," + err.Error())
									}
								} else if *DeviceInfoDetailListData.ModbusTCPType == 4 {
									//采集到的数据
									valueByte, err := stringToUint16Array(value) //转换后的数据
									if err != nil {
										util.Error("modbus上行协议数据更新失败,name:" + sb.Name + ",ID:" + strconv.FormatInt(DeviceInfoDetailListData.ID, 10) + ",err:功能码4 " + err.Error())
									}
									err = mc.NodeRegister.WriteInputs(*DeviceInfoDetailListData.ModbusTCPAddressID, valueByte)
									if err != nil {
										util.Error("modbus上行协议数据更新失败,name:" + sb.Name + ",ID:" + strconv.FormatInt(DeviceInfoDetailListData.ID, 10) + ",err:功能码4数据写入失败," + err.Error())
									}
								}

							}
						}
					}
				}
			}
		}
	}
}

// 把字符串拆解成2字节的十六进制 12345678=uint16{0x1234, 0x5678}
func stringToUint16Array(str string) ([]uint16, error) {
	// 确保字符串长度为偶数
	if len(str)%4 != 0 {
		return nil, fmt.Errorf("字符串长度必须是偶数")
	}

	// 计算结果切片的长度
	result := make([]uint16, len(str)/4)

	// 将每两个字符解析为一个uint16值
	for i := 0; i < len(str); i += 4 {
		val, err := parseUint16(str[i : i+4])
		if err != nil {
			return nil, err
		}
		result[i/4] = val
	}

	return result, nil
}

func parseUint16(s string) (uint16, error) {
	// 将两个字符的字符串解析为一个uint16值
	val, err := strconv.ParseUint(s, 16, 16)
	if err != nil {
		return 0, fmt.Errorf("解析失败：%v", err)
	}
	return uint16(val), nil
}
